package cn.ug.operation.service.impl;

import cn.ug.config.RedisGlobalLock;
import cn.ug.core.ensure.Ensure;
import cn.ug.operation.bean.CupGuessUserBean;
import cn.ug.operation.mapper.CupGuessUserMapper;
import cn.ug.operation.mapper.CupJoinUserMapper;
import cn.ug.operation.mapper.entity.CupGuessUser;
import cn.ug.operation.mapper.entity.CupJoinUser;
import cn.ug.operation.service.CupGuessUserService;
import cn.ug.util.UF;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class CupGuessUserServiceImpl implements CupGuessUserService {
    @Autowired
    private CupGuessUserMapper cupGuessUserMapper;
    @Autowired
    private CupJoinUserMapper cupJoinUserMapper;
    @Resource
    private RedisGlobalLock redisGlobalLock;

    @Override
    public boolean save(CupGuessUser guessUser) {
        if (guessUser != null) {
            String key = "operation:game:guess:"+guessUser.getMemberId();
            try {
                if(redisGlobalLock.lock(key, 5, TimeUnit.SECONDS)) {
                    CupGuessUserBean bean = cupGuessUserMapper.findByMemberIdAndGameId(guessUser.getMemberId(), guessUser.getGameId());
                    if (bean != null) {
                        return false;
                    }
                    CupJoinUser joinUser = cupJoinUserMapper.findByMemberId(guessUser.getMemberId());
                    if (joinUser == null || joinUser.getBalance() < 1) {
                        return false;
                    }
                    guessUser.setId(UF.getRandomUUID());
                    guessUser.setAddTime(LocalDateTime.now());
                    int row = cupGuessUserMapper.insert(guessUser);
                    if (row > 0) {
                        row = cupJoinUserMapper.updateBalanceByMemberId(guessUser.getMemberId(), -1);
                        if (row < 1) {
                            Ensure.that(true).isTrue("00000005");
                        }
                        return true;
                    }
                }
            } finally {
                redisGlobalLock.unlock(key);
            }
        }
        return false;
    }

    @Override
    public CupGuessUserBean getGuessUser(String memberId, String gameId) {
        if (StringUtils.isNotBlank(memberId) && StringUtils.isNotBlank(gameId)) {
            return cupGuessUserMapper.findByMemberIdAndGameId(memberId, gameId);
        }
        return null;
    }

    @Override
    public List<CupGuessUserBean> list(String startDate, String endDate, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        params.put("offset", offset);
        params.put("size", size);
        return cupGuessUserMapper.query(params);
    }

    @Override
    public int count(String startDate, String endDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        return cupGuessUserMapper.count(params);
    }

    @Override
    public boolean updateGuessResult(String gameId, int result) {
        if (StringUtils.isNotBlank(gameId)) {
            return cupGuessUserMapper.updateGuessResult(gameId, result) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public boolean updateMissGuessResult(String gameId, int result) {
        if (StringUtils.isNotBlank(gameId)) {
            return cupGuessUserMapper.updateMissGuessResult(gameId, result) > 0 ? true : false;
        }
        return false;
    }
}
